import { Component } from '@angular/core';
import { ICellEditorAngularComp } from '@ag-grid-community/angular';
import {
  fillField,
  getText,
  getValueUsingField,
  missing,
  missingOrEmptyObject,
  replaceAll,
  type,
} from '../../../utils/utils';
import { ApiService } from '@core/services/http/api.service';
import { SearchService } from '@core/services/search.service';
import { of, Subject } from 'rxjs';
import { debounceTime, distinctUntilChanged, map, switchMap, tap } from 'rxjs/operators';
import { ApesMessageService } from '@shared/apes/message';
import { ExpressionService } from '@core/services/expression/ExpressionService';

@Component({
  selector: 'apes-cell-chart-select',
  template: `
    <div class="apes-multiple-select" [ngStyle]="{'width': params.column.actualWidth+'px' }">
      <apes-input-group apesSearch [apesSuffix]="multipleSelectButton">
        <input placeholder="input here"
               apes-input
               [(ngModel)]="inputValue"
               (ngModelChange)="search($event)"
               (keydown)="onKeyDown($event)"
               [apesAutocomplete]="auto"/>
      </apes-input-group>
      <ng-template #multipleSelectButton>
        <button apes-button apesType="primary" (click)="test1()" apesSearch class="apes-multiple-select-btn">
          科目
        </button>
      </ng-template>
      <apes-autocomplete #auto>
        <apes-auto-option *ngFor="let option of options" #child (click)="clickOption($event,option)"
                          [apesLabel]="option.name">
          {{option.code}}:{{option.name}}
        </apes-auto-option>
      </apes-autocomplete>
    </div>
    <div class="multiple-select" [class.apes-secondary-select]="multipleSelectClass">
      <div apes-row [apesGutter]="8" *ngFor="let data of itemsData;let i = index">
        <div class="multiple-select-main">
          <div apes-col [apesMd]="4" style="height: 28px;line-height: 28px">{{data.auxName}}</div>
          <div apes-col [apesMd]="20">
            <ng-select [items]="childData"
                       [typeahead]="searchChildInput$"
                       (focus)="setApi(data)"
                       bindLabel="name"
                       bindValue="id"
                       (change)="secondaryValue($event,data,i)">
              <ng-template ng-label-tmp let-item="item" let-clear="clear">
                <span class="ng-value-label">{{formatter(item, getValueFormatter())}}</span>
                <span class="ng-value-icon right" (click)="clear(item)" aria-hidden="true">×</span>
              </ng-template>
              <ng-template ng-option-tmp let-item="item">
                <div class="ng-option-flex">
                  <span style="text-align: right">{{formatter(item, getDownFormatter())}}</span>
                </div>
              </ng-template>
            </ng-select>
          </div>
        </div>
      </div>
    </div>
  `,
  styles: [``],
})
export class EditorChartSelectComponent implements ICellEditorAngularComp {
  inputValue: any;
  params: any;
  apesConfig: any;
  ctx: any;
  options = [];

  searchSelectApi: string;
  width = 0;
  contractLoading = false;
  private _current = 0;
  private _pages = 0;
  private _searchText = '';

  searchInput$ = new Subject<string>();

  multipleSelectClass = true;

  itemsData = [];
  selectIndex = 0;

  childData = [];
  childApi = '';
  domain = {
    'filters': [{ 'field': 'id', 'operator': 'LIKE', 'value': '{{value}}' }, {
      'field': 'name',
      'operator': 'LIKE',
      'value': '{{value}}',
    }], 'groups': [], 'operator': 'or',
  };
  searchChildInput$ = new Subject<string>();

  constructor(
    private apiService: ApiService,
    protected searchService: SearchService,
    protected msg: ApesMessageService,
    protected expressionService: ExpressionService,
  ) {
    this.loadData();
  }

  agInit(params: any): void {
    this.params = params;
    if (typeof params.value != 'object') {
      this.inputValue = params.value;
    } else if (typeof params.value == 'object' || params.value != null) {
      this.inputValue = params.value['code'];
      // this.search(this.inputValue);
    }
    this.ctx = params.context;
    this.apesConfig = this.extend(params);
    this.apesConfig = { ...this.apesConfig, ...params['column']['colDef'] };
    this.searchSelectApi = this.params.api;
    this.width = this.params.width;

    if (!missingOrEmptyObject(params.value)) {
      this.options = [params.value];
    }
  }

  extend(data: any) {
    let result = {};
    for (let key in data) {
      let value = data[key];
      if (key === 'context') {
        result['ctx'] = value;
      } else {
        result[key] = value;
      }
    }
    return result;
  }

  isPopup(): boolean {
    return true;
  }

  onBackFillData(value: any): void {
    this.options = [];
    this.inputValue = value['name'];
    this.params.value = value;
    this.selectIndex = 0;
    if (value['auxFlag'] && this.multipleSelectClass) {
      this.itemsData = [];
      this.multipleSelectClass = false;
      value['aux'].map(item => {
        if (item.domain == undefined || item.domain == null || item.domain == '') {
          item['domain'] = {
            'filters': [{'field': 'id', 'operator': 'LIKE', 'value': '{{value}}'}, {
              'field': 'name',
              'operator': 'LIKE',
              'value': '{{value}}',
            }], 'groups': [], 'operator': 'or',
          };
        } else if(typeof item['domain'] == 'string'){
          item['domain'] = JSON.parse(item.domain);
        }
        item.auxName = item.auxName;
        this.itemsData.push(item);
        this.loadChildData();
      });
    }
    return;
  }

  setApi(data) {
    this.childApi = data.api;
    this.childData = [];
    this.domain = data.domain;
    this._searchText = '';
  }

  secondaryValue(value, data, index) {
    data['value'] = value;
  }

  test1() {
    this.params.stopEditing();
    this.params.api.setFocusedCell(0, 'test', null);
    this.params.api.startEditingCell({
      rowIndex: 0,
      colKey: 'test',
      rowPinned: null,
      keyPress: null,
      charPress: null,
    });
  }

  clickOption(data, value) {
    this.multipleSelectClass = true;
    this.onBackFillData(value);
    if (value['auxFlag']) {
      this.preventDefaultAndPropagation(data);
    }
  }

  getValue(): any {
    let result;
    this.multipleSelectClass = true
    if (this.inputValue == null || this.inputValue == undefined || this.inputValue == '') {
      result = undefined;
      this.params.value = undefined;
      this.itemsData = [];
    } else {
      if (typeof this.inputValue == 'object') {
        this.params.value = this.inputValue;
        result = this.inputValue;
      } else {
        result = this.params.value;
      }
      if (result && this.itemsData.length > 0) {
        this.params.node.setDataValue('voucherAuxiliaryList', '');
        this.params.node.setDataValue('aux', '');
        this.params.node.setDataValue('cashFlow', '');

        let t = '';
        let cashFlow;
        let voucherAuxiliaryList = [];
        this.itemsData.map((item, index) => {
          if (item['value']) {
            if (item['project_id'] == 'cashFlow') {
              cashFlow = item['value'];
            } else {
              t += item['auxName'] + ':[(' + item['value']['id'] + ')' + item['value']['name'] + ']';
              if (index != 0 && index < this.itemsData.length - 1) {
                t += ',';
              }
              item['accountingOperatingChartAuxiliary'] = {id: item.id, name: item.name};
              item['code'] = item.value.id;
              item['name'] = item.value.name;
              voucherAuxiliaryList.push(item);
            }
          } else {
            result = undefined;
            this.params.value = undefined;
          }
        });
        if (voucherAuxiliaryList.length > 0) {
          this.params.node.setDataValue('voucherAuxiliaryList', voucherAuxiliaryList);
          this.params.node.setDataValue('aux', t);
        }
        if (cashFlow) {
          this.params.node.setDataValue('cashFlow', cashFlow);
        }
      }
    }
    if (!result) {
      this.params.node.setDataValue('voucherAuxiliaryList', '');
      this.params.node.setDataValue('aux', '');
      this.params.node.setDataValue('cashFlow', '');
      this.msg.warning('未填写完整，请重新填写！', {apesDuration: 3000});
    }
    return result;
  }

  onKeyDown(event): void {
    let key = event.which || event.keyCode;
    let length = this.options.length - 1;
    let index = this.selectIndex;
    if (key === 37 || key === 38 || key === 39 || key === 40) {
      this.preventDefaultAndPropagation(event);
      if (key == 38) {
        index -= 1;
        if (index < 0) {
          this.selectIndex = length;
        } else {
          this.selectIndex -= 1;
        }
      } else if (key == 40) {
        index += 1;
        if (index > length) {
          this.selectIndex = 0;
        } else {
          this.selectIndex += 1;
        }
      }
    }
    if (key == 13) {
      this.clickOption(event, this.options[index]);
    }
    // event.stopPropagation();
  }

  private preventDefaultAndPropagation(event) {
    event.preventDefault();
    event.stopPropagation();
  }

  /** 查询数据 */
  search(value) {
    if (missing(value) || value.length < 4) return;
    this.searchInput$.next(value);
  }

  private loadData() {
    this.searchInput$.pipe(
      debounceTime(300),
      distinctUntilChanged(),
      tap(() => this.contractLoading = true),
      switchMap((term) => {
        if (missing(term)) {
          this.contractLoading = false;
          return of([]);
        }
        if (this._searchText === term) return of([]);
        this._current = 0;
        this._searchText = term;
        const data = this.getApiParams();
        return this.apiService.post(this.searchSelectApi, data).pipe(
          map((res) => {
              this.options = [];
              this._searchText = term;
              this.options = this.options.concat(res);
              return res;
            },
          ),
          tap(() => this.contractLoading = false),
        );
      }),
    ).subscribe();
  }

  private loadChildData() {
    this.searchChildInput$.pipe(
      debounceTime(300),
      distinctUntilChanged(),
      tap(() => this.contractLoading = true),
      switchMap((term) => {
        if (missing(term)) {
          this.contractLoading = false;
          return of([]);
        }
        if (this._searchText === term) return of([]);
        this._current = 0;
        this._searchText = term;
        const data = this.getApiParams();
        return this.apiService.post(this.childApi, data).pipe(
          map((res) => {
              this.childData = [];
              this._searchText = term;
              this.childData = this.childData.concat(res.content);
              return res.content;
            },
          ),
          tap(() => this.contractLoading = false),
        );
      }),
    ).subscribe();
  }

  getApiParams() {
    const data = { key: this._searchText, company: this.ctx.model.company.id, page: this._current, size: 50 };
    if (this.domain) {
      const group = fillField(this.domain, this.ctx, false, this._searchText);
      data['group'] = group;
    }
    return data;
  }

  getValueFormatter(): string {
    return this.params.valueFormatter || '\'[ \' + value.id + \' ]\' + \' \' + value.name';
  }

  getDownFormatter(): string {
    return this.params.downFormatter || '\'[ \' + value.id + \' ]\' + \' \' + value.name';
  }


  formatter(value: any, expression: string) {
    return this.expressionService.evaluate(expression, {
      context: this.ctx,
      model: this.ctx.model,
      value: value,
    });
  }
}
